package com.xiejr.actuator.socket.abstracts;

import com.alibaba.fastjson.JSON;
import com.xiejr.actuator.exceptioin.SocketActuatorException;
import com.xiejr.actuator.socket.Topic;
import com.xiejr.actuator.socket.dto.TopicMessageDto;
import com.xiejr.actuator.socket.model.SocketClient;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StringUtils;

import javax.websocket.Session;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

/**
 * @program: socket-actuator-spring-boot-starter
 * @description: 主题式websocket
 * @author: xjr
 * @create: 2020-07-09 17:06
 **/
@Slf4j
public abstract class TopicWebsocketHelper extends AbstractWebsocketHelper {
    /**
     ** 保存不同主题的处理组件
     */
    private static Map<String,Topic> HANDLERS=new HashMap<>(20);

    /**
     *
     * @param bindingKey 主题绑定
     * @return void
     * @author xiejr
     * @create: 下发消息
     * @date 2020/7/12 12:44
     */
    public static void notifyConsumers(String bindingKey) throws SocketActuatorException{
        getSocketClients().forEach((uuid,client)->{
            Session session=client.getSession();
            if (client.getBinding()!=null){
                try {
                    String result=client.getBinding().delivery(bindingKey);
                    if (result!=null){
                        session.getBasicRemote().sendText(result);
                    }
                }catch (Exception ex){
                    log.error("message delivery occurred something wrong,details is {}",ex.getMessage());
                    throw new SocketActuatorException(ex.getMessage());
                }
            }

        });
    }

    @Override
    protected SocketClient addSession(Session session) throws Exception {
        SocketClient socketClient=super.addSession(session);
        String topic=session.getQueryString().replaceAll("topic=","");
        if (StringUtils.isEmpty(topic)){
            throw new SocketActuatorException("路径参数错误");
        }
        socketClient.setBinding(getHandlerComponent(session.getQueryString().replaceAll("topic=","")));
        notifyConsumers(topic);
        return socketClient;
    }

    /**
     *
     * @param session 消息会话
     * @param message 消息内容
     * @return void
     * @author xiejr
     * @create: 默认为订阅主题切换
     * @date 2020/7/12 14:08
     */
    @Override
    public void message(Session session, String message) throws SocketActuatorException {
        TopicMessageDto topicMessage=null;
        try {
            topicMessage= JSON.parseObject(message, TopicMessageDto.class);
        }catch (Exception ex){
            throw new SocketActuatorException("客户端消息格式错误,请确认！");
        }

        if (topicMessage.isTransfer()){
            Topic topic=getHandlerComponent(topicMessage.getTopic());
            SOCKET_CLIENTS.get(this.uuid).setBinding(topic);
            notifyConsumers(topicMessage.getTopic());
        }
        refreshHeart(LocalDateTime.now(),message);
    }

    /**
     *
     * @description 根据字符串获取主题的处理组件
     * @param topic: 主题
     * @author xiejiarong
     * @date 2020年07月13日 11:15
     */
    public static Topic getHandlerComponent(String topic) throws SocketActuatorException{
        return Optional.ofNullable(HANDLERS.get(topic)).orElseThrow(()->new SocketActuatorException("找不到该主题的业务处理组件"));
    }

    /**
     *
     * @description 设置处理器组件
     * @param topicMap:处理器组件列表
     * @author xiejiarong
     * @date 2020年07月13日 11:17
     */
    public static void setHandlers(Map<String,Topic> topicMap){
        HANDLERS=topicMap;
    }


}
